<html><body>
<pre class="prettyprint">
        // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

        #ifndef UNITY_STANDARD_UTILS_INCLUDED
        #define UNITY_STANDARD_UTILS_INCLUDED
        
        #include "UnityCG.cginc"
        #include "UnityStandardConfig.cginc"
        
        // Helper functions, maybe move into UnityCG.cginc
        
        half <a name="SpecularStrength">SpecularStrength</a>(half3 specular)
        {
            #if (SHADER_TARGET < 30)
                // SM2.0: instruction count limitation
                // SM2.0: simplified SpecularStrength
                return specular.r; // Red channel - because most metals are either monocrhome or with redish/yellowish tint
            #else
                return max (max (specular.r, specular.g), specular.b);
            #endif
        }
        
        // Diffuse/Spec Energy conservation
        inline half3 <a name="EnergyConservationBetweenDiffuseAndSpecular">EnergyConservationBetweenDiffuseAndSpecular</a> (half3 albedo, half3 specColor, out half oneMinusReflectivity)
        {
            oneMinusReflectivity = 1 - SpecularStrength(specColor);
            #if !UNITY_CONSERVE_ENERGY
                return albedo;
            #elif UNITY_CONSERVE_ENERGY_MONOCHROME
                return albedo * oneMinusReflectivity;
            #else
                return albedo * (half3(1,1,1) - specColor);
            #endif
        }
        
        inline half <a name="OneMinusReflectivityFromMetallic">OneMinusReflectivityFromMetallic</a>(half metallic)
        {
            // We'll need oneMinusReflectivity, so
            //   1-reflectivity = 1-lerp(dielectricSpec, 1, metallic) = lerp(1-dielectricSpec, 0, metallic)
            // store (1-dielectricSpec) in unity_ColorSpaceDielectricSpec.a, then
            //   1-reflectivity = lerp(alpha, 0, metallic) = alpha + metallic*(0 - alpha) =
            //                  = alpha - metallic * alpha
            half oneMinusDielectricSpec = unity_ColorSpaceDielectricSpec.a;
            return oneMinusDielectricSpec - metallic * oneMinusDielectricSpec;
        }
        
        inline half3 <a name="DiffuseAndSpecularFromMetallic">DiffuseAndSpecularFromMetallic</a> (half3 albedo, half metallic, out half3 specColor, out half oneMinusReflectivity)
        {
            specColor = lerp (unity_ColorSpaceDielectricSpec.rgb, albedo, metallic);
            oneMinusReflectivity = OneMinusReflectivityFromMetallic(metallic);
            return albedo * oneMinusReflectivity;
        }
        
        inline half3 <a name="PreMultiplyAlpha">PreMultiplyAlpha</a> (half3 diffColor, half alpha, half oneMinusReflectivity, out half outModifiedAlpha)
        {
            #if defined(_ALPHAPREMULTIPLY_ON)
                // NOTE: shader relies on pre-multiply alpha-blend (_SrcBlend = One, _DstBlend = OneMinusSrcAlpha)
        
                // Transparency 'removes' from Diffuse component
                diffColor *= alpha;
        
                #if (SHADER_TARGET < 30)
                    // SM2.0: instruction count limitation
                    // Instead will sacrifice part of physically based transparency where amount Reflectivity is affecting Transparency
                    // SM2.0: uses unmodified alpha
                    outModifiedAlpha = alpha;
                #else
                    // Reflectivity 'removes' from the rest of components, including Transparency
                    // outAlpha = 1-(1-alpha)*(1-reflectivity) = 1-(oneMinusReflectivity - alpha*oneMinusReflectivity) =
                    //          = 1-oneMinusReflectivity + alpha*oneMinusReflectivity
                    outModifiedAlpha = 1-oneMinusReflectivity + alpha*oneMinusReflectivity;
                #endif
            #else
                outModifiedAlpha = alpha;
            #endif
            return diffColor;
        }
        
        // Same as ParallaxOffset in Unity CG, except:
        //  *) precision - half instead of float
        half2 <a name="ParallaxOffset1Step">ParallaxOffset1Step</a> (half h, half height, half3 viewDir)
        {
            h = h * height - height/2.0;
            half3 v = normalize(viewDir);
            v.z += 0.42;
            return h * (v.xy / v.z);
        }
        
        half <a name="LerpOneTo">LerpOneTo</a>(half b, half t)
        {
            half oneMinusT = 1 - t;
            return oneMinusT + b * t;
        }
        
        half3 <a name="LerpWhiteTo">LerpWhiteTo</a>(half3 b, half t)
        {
            half oneMinusT = 1 - t;
            return half3(oneMinusT, oneMinusT, oneMinusT) + b * t;
        }
        
        half3 <a name="UnpackScaleNormalDXT5nm">UnpackScaleNormalDXT5nm</a>(half4 packednormal, half bumpScale)
        {
            half3 normal;
            normal.xy = (packednormal.wy * 2 - 1);
            #if (SHADER_TARGET >= 30)
                // SM2.0: instruction count limitation
                // SM2.0: normal scaler is not supported
                normal.xy *= bumpScale;
            #endif
            normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy)));
            return normal;
        }
        
        half3 <a name="UnpackScaleNormalRGorAG">UnpackScaleNormalRGorAG</a>(half4 packednormal, half bumpScale)
        {
            #if defined(UNITY_NO_DXT5nm)
                half3 normal = packednormal.xyz * 2 - 1;
                #if (SHADER_TARGET >= 30)
                    // SM2.0: instruction count limitation
                    // SM2.0: normal scaler is not supported
                    normal.xy *= bumpScale;
                #endif
                return normal;
            #else
                // This do the trick
                packednormal.x *= packednormal.w;
        
                half3 normal;
                normal.xy = (packednormal.xy * 2 - 1);
                #if (SHADER_TARGET >= 30)
                    // SM2.0: instruction count limitation
                    // SM2.0: normal scaler is not supported
                    normal.xy *= bumpScale;
                #endif
                normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy)));
                return normal;
            #endif
        }
        
        half3 <a name="UnpackScaleNormal">UnpackScaleNormal</a>(half4 packednormal, half bumpScale)
        {
            return UnpackScaleNormalRGorAG(packednormal, bumpScale);
        }
        
        half3 <a name="BlendNormals">BlendNormals</a>(half3 n1, half3 n2)
        {
            return normalize(half3(n1.xy + n2.xy, n1.z*n2.z));
        }
        
        half3x3 <a name="CreateTangentToWorldPerVertex">CreateTangentToWorldPerVertex</a>(half3 normal, half3 tangent, half tangentSign)
        {
            // For odd-negative scale transforms we need to flip the sign
            half sign = tangentSign * unity_WorldTransformParams.w;
            half3 binormal = cross(normal, tangent) * sign;
            return half3x3(tangent, binormal, normal);
        }
        
        //-------------------------------------------------------------------------------------
        half3 <a name="ShadeSHPerVertex">ShadeSHPerVertex</a> (half3 normal, half3 ambient)
        {
            #if UNITY_SAMPLE_FULL_SH_PER_PIXEL
                // Completely per-pixel
                // nothing to do here
            #elif (SHADER_TARGET < 30) || UNITY_STANDARD_SIMPLE
                // Completely per-vertex
                ambient += max(half3(0,0,0), ShadeSH9 (half4(normal, 1.0)));
            #else
                // L2 per-vertex, L0..L1 & gamma-correction per-pixel
        
                // NOTE: SH data is always in Linear AND calculation is split between vertex & pixel
                // Convert ambient to Linear and do final gamma-correction at the end (per-pixel)
                #ifdef UNITY_COLORSPACE_GAMMA
                    ambient = GammaToLinearSpace (ambient);
                #endif
                ambient += SHEvalLinearL2 (half4(normal, 1.0));     // no max since this is only L2 contribution
            #endif
        
            return ambient;
        }
        
        half3 <a name="ShadeSHPerPixel">ShadeSHPerPixel</a> (half3 normal, half3 ambient, float3 worldPos)
        {
            half3 ambient_contrib = 0.0;
        
            #if UNITY_SAMPLE_FULL_SH_PER_PIXEL
                // Completely per-pixel
                #if UNITY_LIGHT_PROBE_PROXY_VOLUME
                    if (unity_ProbeVolumeParams.x == 1.0)
                        ambient_contrib = SHEvalLinearL0L1_SampleProbeVolume(half4(normal, 1.0), worldPos);
                    else
                        ambient_contrib = SHEvalLinearL0L1(half4(normal, 1.0));
                #else
                    ambient_contrib = SHEvalLinearL0L1(half4(normal, 1.0));
                #endif
        
                    ambient_contrib += SHEvalLinearL2(half4(normal, 1.0));
        
                    ambient += max(half3(0, 0, 0), ambient_contrib);
        
                #ifdef UNITY_COLORSPACE_GAMMA
                    ambient = LinearToGammaSpace(ambient);
                #endif
            #elif (SHADER_TARGET < 30) || UNITY_STANDARD_SIMPLE
                // Completely per-vertex
                // nothing to do here. Gamma conversion on ambient from SH takes place in the vertex shader, see ShadeSHPerVertex.
            #else
                // L2 per-vertex, L0..L1 & gamma-correction per-pixel
                // Ambient in this case is expected to be always Linear, see ShadeSHPerVertex()
                #if UNITY_LIGHT_PROBE_PROXY_VOLUME
                    if (unity_ProbeVolumeParams.x == 1.0)
                        ambient_contrib = SHEvalLinearL0L1_SampleProbeVolume (half4(normal, 1.0), worldPos);
                    else
                        ambient_contrib = SHEvalLinearL0L1 (half4(normal, 1.0));
                #else
                    ambient_contrib = SHEvalLinearL0L1 (half4(normal, 1.0));
                #endif
        
                ambient = max(half3(0, 0, 0), ambient+ambient_contrib);     // include L2 contribution in vertex shader before clamp.
                #ifdef UNITY_COLORSPACE_GAMMA
                    ambient = LinearToGammaSpace (ambient);
                #endif
            #endif
        
            return ambient;
        }
        
        //-------------------------------------------------------------------------------------
        inline float3 <a name="BoxProjectedCubemapDirection">BoxProjectedCubemapDirection</a>(float3 worldRefl, float3 worldPos, float4 cubemapCenter, float4 boxMin, float4 boxMax)
        {
            // Do we have a valid reflection probe?
            UNITY_BRANCH
            if (cubemapCenter.w > 0.0)
            {
                float3 nrdir = normalize(worldRefl);
        
                #if 1
                    float3 rbmax = (boxMax.xyz - worldPos) / nrdir;
                    float3 rbmin = (boxMin.xyz - worldPos) / nrdir;
        
                    float3 rbminmax = (nrdir > 0.0f) ? rbmax : rbmin;
        
                #else // Optimized version
                    float3 rbmax = (boxMax.xyz - worldPos);
                    float3 rbmin = (boxMin.xyz - worldPos);
        
                    float3 select = step (float3(0,0,0), nrdir);
                    float3 rbminmax = lerp (rbmax, rbmin, select);
                    rbminmax /= nrdir;
                #endif
        
                float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
        
                worldPos -= cubemapCenter.xyz;
                worldRefl = worldPos + nrdir * fa;
            }
            return worldRefl;
        }
        
        
        //-------------------------------------------------------------------------------------
        // Derivative maps
        // http://www.rorydriscoll.com/2012/01/11/derivative-maps/
        // For future use.
        
        // Project the surface gradient (dhdx, dhdy) onto the surface (n, dpdx, dpdy)
        half3 <a name="CalculateSurfaceGradient">CalculateSurfaceGradient</a>(half3 n, half3 dpdx, half3 dpdy, half dhdx, half dhdy)
        {
            half3 r1 = cross(dpdy, n);
            half3 r2 = cross(n, dpdx);
            return (r1 * dhdx + r2 * dhdy) / dot(dpdx, r1);
        }
        
        // Move the normal away from the surface normal in the opposite surface gradient direction
        half3 <a name="PerturbNormal">PerturbNormal</a>(half3 n, half3 dpdx, half3 dpdy, half dhdx, half dhdy)
        {
            //TODO: normalize seems to be necessary when scales do go beyond the 2...-2 range, should we limit that?
            //how expensive is a normalize? Anything cheaper for this case?
            return normalize(n - CalculateSurfaceGradient(n, dpdx, dpdy, dhdx, dhdy));
        }
        
        // Calculate the surface normal using the uv-space gradient (dhdu, dhdv)
        half3 <a name="CalculateSurfaceNormal">CalculateSurfaceNormal</a>(half3 position, half3 normal, half2 gradient, half2 uv)
        {
            half3 dpdx = ddx(position);
            half3 dpdy = ddy(position);
        
            half dhdx = dot(gradient, ddx(uv));
            half dhdy = dot(gradient, ddy(uv));
        
            return PerturbNormal(normal, dpdx, dpdy, dhdx, dhdy);
        }
        
        
        #endif // UNITY_STANDARD_UTILS_INCLUDED
</pre>
<script src="https://xibanya.github.io/ShaderTutorials/CGIncludes/code-prettify/loader/run_prettify.js?skin=vscode"></script>
<script src="https://xibanya.github.io/ShaderTutorials/CGIncludes/Data/link_definitions.js"></script>
</body></html>
